#include "widgets/configCtl.h"

#include <QDebug>
#include <QTimer>

#include <map>
#include <vector>

#include "node/node.h"

ConfigCtl::ConfigCtl(QComboBox *qConfigBox, QComboBox *qConfigValBox, QPushButton *qBtnConfigSubmit,
                     QComboBox *qFreeConfigBox, QLineEdit *qFreeConfigValText, QPushButton *qBtnFreeConfigSubmit,
                     QPushButton *qBtnConfigRefresh, QTextEdit *qConfigResultText, std::shared_ptr<AppNode> appNode,
                     QWidget *parent)
    : QWidget(parent), qConfigBox_(qConfigBox), qConfigValBox_(qConfigValBox), qBtnConfigSubmit_(qBtnConfigSubmit),
      qFreeConfigBox_(qFreeConfigBox), qFreeConfigValText_(qFreeConfigValText),
      qBtnFreeConfigSubmit_(qBtnFreeConfigSubmit), qBtnConfigRefresh_(qBtnConfigRefresh),
      qConfigResultText_(qConfigResultText), appNode_(appNode) {
    // 选项配置
    connect(qConfigBox_, QOverload<const QString &>::of(&QComboBox::currentTextChanged), this,
            &ConfigCtl::onConfigListActivated);
    connect(qBtnConfigSubmit_, &QPushButton::clicked, this, &ConfigCtl::onBtnConfigClicked);

    // 自由配置
    // connect(freeConfigList_, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
    // &ConfigCtl::onFreeConfigListActivated);
    connect(qFreeConfigBox_, QOverload<const QString &>::of(&QComboBox::currentTextChanged), this,
            &ConfigCtl::onFreeConfigListActivated);
    connect(qBtnFreeConfigSubmit_, &QPushButton::clicked, this, &ConfigCtl::onBtnFreeConfigClicked);

    // 刷新配置
    connect(qBtnConfigRefresh_, &QPushButton::clicked, this, &ConfigCtl::onBtnConfigRefreshClicked);
}

ConfigCtl::~ConfigCtl() {}

void ConfigCtl::updateQConfigValBox(const std::string &configName) {
    qConfigValBox_->clear();
    auto v = configListMap_.find(configName);
    if (v != configListMap_.end()) {
        const auto &valVec = v->second;
        for (const auto &it : valVec) {
            qConfigValBox_->addItem(it.c_str());
        }
    } else {
        qConfigValBox_->addItem("No available value");
    }
}

bool ConfigCtl::updateAllConfigInfo() {
    qConfigResultText_->setText("配置参数同步开始，请等待...");
    // 从mbot-body获取参数详细信息
    auto params = appNode_->listParameters();

    if (params.empty()) {
        qConfigResultText_->append("配置参数同步失败");
        return false;
    }

    for (auto it = params.begin(); it != params.end(); it++) {
        auto valVec = it->second;
        if (valVec.size() > 0) {
            configListMap_[std::string(it->first)] = valVec;
            qConfigBox_->addItem(it->first.c_str());
        } else {
            qFreeConfigBox_->addItem(it->first.c_str());
        }
    }

    qConfigResultText_->append("配置参数同步成功");
    return true;
}

bool ConfigCtl::updateAllConfigVal() {
    qConfigResultText_->setText("配置刷新开始，请等待...");
    // 从mbot-body获取参数当前值
    auto params = appNode_->getAllParameters();

    if (params.empty()) {
        qConfigResultText_->append("配置刷新失败");
        return false;
    }

    for (auto it = params.begin(); it != params.end(); it++) {
        auto val = it->second;
        if (val.size() > 0) {
            currentConfigValMap_[std::string(it->first)] = val;
        }
    }

    qConfigResultText_->append("配置刷新成功");
    return true;
}

void ConfigCtl::updateConfigVal(const std::string &configName, const std::string &configVal) {
    currentConfigValMap_[std::string(configName)] = configVal;
}

void ConfigCtl::onConfigListActivated(const QString &text) {
    std::string configKey = text.toStdString();
    updateQConfigValBox(configKey);

    updateQConfigValBox(configKey);
    qConfigValBox_->setCurrentText(currentConfigValMap_[configKey].c_str());
}

void ConfigCtl::onBtnConfigClicked() {
    qConfigResultText_->setText("配置开始，请等待...");

    std::string configKey = qConfigBox_->currentText().toStdString();
    std::string configVal = qConfigValBox_->currentText().toStdString();

    if (appNode_->setParameter(configKey, configVal)) {
        updateConfigVal(configKey, configVal);
        qConfigResultText_->append("配置成功");
    } else {
        qConfigResultText_->append("配置失败");
    }
}

void ConfigCtl::onBtnConfigRefreshClicked() {
    if (!updateAllConfigInfo() || !updateAllConfigVal()) {
        return;
    }

    qConfigBox_->clear();
    qFreeConfigBox_->clear();
    qConfigValBox_->clear();
    qFreeConfigValText_->clear();
    qConfigResultText_->clear();
}

void ConfigCtl::onFreeConfigListActivated(const QString &text) {
    std::string configKey = text.toStdString();
    qFreeConfigValText_->setText(currentConfigValMap_[configKey].c_str());
}

void ConfigCtl::onBtnFreeConfigClicked() {
    qConfigResultText_->setText("配置开始，请等待...");

    // 使用 QTimer 延迟耗时操作，否则会阻塞 UI 线程，上述代码会导致 UI 无法响应
    // 0 毫秒后执行
    // 这里使用 lambda 表达式来捕获 this 指针
    QTimer::singleShot(0, this, [this]() {
        std::string configKey = qFreeConfigBox_->currentText().toStdString();
        std::string configVal = qFreeConfigValText_->text().toStdString();

        if (appNode_->setParameter(configKey, configVal)) {
            updateConfigVal(configKey, configVal);
            qConfigResultText_->append("配置成功");
        } else {
            qConfigResultText_->append("配置失败");
        }
    });
}
